<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<title>Binary Predicates</title>
<link href="../docs-assets/Breadcrumbs.css" rel="stylesheet" rev="stylesheet" type="text/css">
		<meta name="viewport" content="width=device-width initial-scale=1">
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
		<meta http-equiv="Content-Language" content="en-gb">

<link href="../docs-assets/Contents.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Progress.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Navigation.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Fonts.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Base.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script>
MathJax = {
	tex: {
		inlineMath: '$', '$'], ['\\(', '\\)'
	},
	svg: {
		fontCache: 'global'
	}
};
</script>
<script type="text/javascript" id="MathJax-script" async
	src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>

<script>
function togglePopup(material_id) {
  var popup = document.getElementById(material_id);
  popup.classList.toggle("show");
}
</script>

<link href="../docs-assets/Popups.css" rel="stylesheet" rev="stylesheet" type="text/css">
<script src="http://code.jquery.com/jquery-1.12.4.min.js"
	integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>

<script src="../docs-assets/Bigfoot.js"></script>
<link href="../docs-assets/Bigfoot.css" rel="stylesheet" rev="stylesheet" type="text/css">
<link href="../docs-assets/Colours.css" rel="stylesheet" rev="stylesheet" type="text/css">
		
	</head>
	<body class="commentary-font">
		<nav role="navigation">
		<h1><a href="../index.html"><img src="../docs-assets/Inform.png" height=72> </a></h1>
<ul><li><a href="../index.html">home</a></li>
</ul><h2>Compiler</h2><ul>
<li><a href="../structure.html">structure</a></li>
<li><a href="../inbuildn.html">inbuild</a></li>
<li><a href="../inform7n.html">inform7</a></li>
<li><a href="../intern.html">inter</a></li>
<li><a href="../services.html">services</a></li>
<li><a href="../secrets.html">secrets</a></li>
</ul><h2>Other Tools</h2><ul>
<li><a href="../inblorbn.html">inblorb</a></li>
<li><a href="../inform6.html">inform6</a></li>
<li><a href="../inpolicyn.html">inpolicy</a></li>
</ul><h2>Resources</h2><ul>
<li><a href="../extensions.html">extensions</a></li>
<li><a href="../kits.html">kits</a></li>
</ul><h2>Repository</h2><ul>
<li><a href="https://github.com/ganelson/inform"><img src="../docs-assets/github.png" height=0> github</a></li>
</ul><h2>Related Projects</h2><ul>
<li><a href="https://github.com/ganelson/inweb"><img src="../docs-assets/github.png" height=0> inweb</a></li>
<li><a href="https://github.com/ganelson/intest"><img src="../docs-assets/github.png" height=0> intest</a></li>
</ul>
		</nav>
		<main role="main">
		<!-- Weave of 'Binary Predicates' generated by inweb -->
<div class="breadcrumbs">
    <ul class="crumbs"><li><a href="../index.html">Home</a></li><li><a href="../services.html">Services</a></li><li><a href="index.html">calculus</a></li><li><a href="index.html#3">Chapter 3: Binary Predicates</a></li><li><b>Binary Predicates</b></li></ul></div>
<p class="purpose">To create and manage binary predicates, which are the underlying data structures beneath Inform's relations.</p>

<ul class="toc"><li><a href="3-bp.html#SP1">&#167;1. Introduction</a></li><li><a href="3-bp.html#SP6">&#167;6. Combining the terms</a></li><li><a href="3-bp.html#SP9">&#167;9. Making the equality relation</a></li><li><a href="3-bp.html#SP10">&#167;10. Making a pair of relations</a></li><li><a href="3-bp.html#SP11">&#167;11. BP construction</a></li><li><a href="3-bp.html#SP12">&#167;12. BP and term logging</a></li><li><a href="3-bp.html#SP13">&#167;13. Relation names</a></li><li><a href="3-bp.html#SP15">&#167;15. Miscellaneous access routines</a></li><li><a href="3-bp.html#SP18">&#167;18. Loop schema</a></li></ul><hr class="tocbar">

<p class="commentary firstcommentary"><a id="SP1" class="paragraph-anchor"></a><b>&#167;1. Introduction.</b>A "binary predicate" is a property \(B\) such that for any combination \(x\) and
\(y\), and at any given moment at run-time, \(B(x, y)\) is either true or false.
\(x\) and \(y\) are called its "terms", and are numbered 0 and 1 below.
</p>

<p class="commentary">The classic example is equality, \((x == y)\), which is true if and only if they
are the same value. But Inform has many others. In the Inform documentation,
binary predicates are called "relations". These are grouped by <a href="3-bpf.html#SP1" class="internal">bp_family</a>,
and the <span class="extract"><span class="extract-syntax">family_specific</span></span> field of a BP holds data meaningful only to a
predicate in that family; for example, in a predicate to measure a property,
this would store the property in question and the threshold value.
</p>

<p class="commentary">The calculus module tries to be blind to the nuances of how these families
behave differently from each other, and also to the quite complicated issue
of how to compile supporting code and data structures for use at run-time.
See <a href="../runtime-module/5-rlt.html" class="internal">Relations (in runtime)</a> for all of that.
</p>

<p class="commentary firstcommentary"><a id="SP2" class="paragraph-anchor"></a><b>&#167;2. </b>Each BP has a partner which we call its "reversal".<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> If \(B\) is the
original and \(R\) is its reversal, then \(B(x, y)\) is true if and only if
\(R(y, x)\) is true. Reversals sometimes occur quite naturally in English
language. "To wear" is the reversal of "to be worn by". "Contains" is
the reversal of being "inside".
</p>

<p class="commentary">The following sentences express the same fact:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">The</span><span class="plain-syntax"> </span><span class="identifier-syntax">ball</span><span class="plain-syntax"> </span><span class="identifier-syntax">is</span><span class="plain-syntax"> </span><span class="identifier-syntax">inside</span><span class="plain-syntax"> </span><span class="identifier-syntax">the</span><span class="plain-syntax"> </span><span class="identifier-syntax">trophy</span><span class="plain-syntax"> </span><span class="identifier-syntax">case</span><span class="plain-syntax">. </span><span class="identifier-syntax">The</span><span class="plain-syntax"> </span><span class="identifier-syntax">trophy</span><span class="plain-syntax"> </span><span class="identifier-syntax">case</span><span class="plain-syntax"> </span><span class="identifier-syntax">contains</span><span class="plain-syntax"> </span><span class="identifier-syntax">the</span><span class="plain-syntax"> </span><span class="identifier-syntax">ball</span><span class="plain-syntax">.</span>
</pre>
<p class="commentary">...even though they involve different BPs:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="identifier-syntax">inside</span><span class="plain-syntax">(</span><span class="identifier-syntax">ball</span><span class="plain-syntax">, </span><span class="identifier-syntax">trophy</span><span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax">)</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">contains</span><span class="plain-syntax">(</span><span class="identifier-syntax">trophy</span><span class="plain-syntax"> </span><span class="reserved-syntax">case</span><span class="plain-syntax">, </span><span class="identifier-syntax">ball</span><span class="plain-syntax">)</span>
</pre>
<p class="commentary">So for every pair of BPs \(X\) and \(Y\) which are each other's reversal, Inform
designates one as being "the right way round" and the other as being "the
wrong way round".<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup> Whenever a sentence's meaning involves a BP which is "the
wrong way round", Inform swaps over the terms and replaces the BP by its
reversal, which is "the right way round". The above pair of sentences is
then more easily recognised as a duplicate meaning.
</p>

<ul class="footnotetexts"><li class="footnote" id="fn:1"><p class="inwebfootnote"><sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup> The equality relation is the only BP which is its own reversal: "A is B"
and "B is A" are the same meaning.
<a href="#fnref:1" title="return to text"> &#x21A9;</a></p></li><li class="footnote" id="fn:2"><p class="inwebfootnote"><sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup> This is purely an implementation convenience; there's no real sense in
logic or linguistics in which either way round is better. The equality
relation is always the right way round.
<a href="#fnref:2" title="return to text"> &#x21A9;</a></p></li></ul>
<p class="commentary firstcommentary"><a id="SP3" class="paragraph-anchor"></a><b>&#167;3. </b>Given any binary predicate \(B\), we may wish to perform one of several
possible "tasks" ar run-time. This will require code to be generated, which
is done via a "schema". See <a href="3-bpf.html#SP5" class="internal">BinaryPredicateFamilies::get_schema</a>, but
by default this adopts the one given in the BP's <span class="extract"><span class="extract-syntax">task_functions</span></span> field.
</p>

<p class="commentary firstcommentary"><a id="SP4" class="paragraph-anchor"></a><b>&#167;4. </b>Without further ado:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">typedef</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">bp_family</span><span class="plain-syntax"> *</span><span class="identifier-syntax">relation_family</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">general_pointer</span><span class="plain-syntax"> </span><span class="identifier-syntax">family_specific</span><span class="plain-syntax">; </span><span class="comment-syntax"> details for particular kinds of BP</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">word_assemblage</span><span class="plain-syntax"> </span><span class="identifier-syntax">relation_name</span><span class="plain-syntax">; </span><span class="comment-syntax"> (which might have length 0)</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp_created_at</span><span class="plain-syntax">; </span><span class="comment-syntax"> where declared in the source text</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">debugging_log_name</span><span class="plain-syntax">; </span><span class="comment-syntax"> used when printing propositions to the debug log</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">bp_term_details</span><span class="plain-syntax"> </span><span class="identifier-syntax">term_details</span><span class="plain-syntax">[2]; </span><span class="comment-syntax"> 0 is the left term, 1 is the right</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">reversal</span><span class="plain-syntax">; </span><span class="comment-syntax"> see above</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">right_way_round</span><span class="plain-syntax">; </span><span class="comment-syntax"> was this BP created directly? or is it a reversal of another?</span>

<span class="plain-syntax">    </span><span class="comment-syntax"> how to compile code which tests or forces this BP to be true or false:</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">task_functions</span><span class="plain-syntax">[4]; </span><span class="comment-syntax"> I6 schema for tasks</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop_parent_optimisation_proviso</span><span class="plain-syntax">; </span><span class="comment-syntax"> if not NULL, optimise loops using object tree</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">loop_parent_optimisation_ranger</span><span class="plain-syntax">; </span><span class="comment-syntax"> if not NULL, routine iterating through contents</span>

<span class="plain-syntax">    </span><span class="comment-syntax"> somewhere to stash what we know about these relationships:</span>
<span class="plain-syntax">    </span><span class="constant-syntax">TERM_DOMAIN_CALCULUS_TYPE</span><span class="plain-syntax"> *</span><span class="identifier-syntax">knowledge_about_bp</span><span class="plain-syntax">; </span><span class="comment-syntax"> in Inform, this is an inference subject</span>

<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="identifier-syntax">bp_compilation_data</span><span class="plain-syntax"> </span><span class="identifier-syntax">compilation_data</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">CLASS_DEFINITION</span>
<span class="plain-syntax">} </span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax">;</span>
</pre>
<ul class="endnotetexts"><li>The structure binary_predicate is accessed in 3/bpf and here.</li></ul>
<p class="commentary firstcommentary"><a id="SP5" class="paragraph-anchor"></a><b>&#167;5. </b>The <a href="../linguistics-module/index.html" class="internal">linguistics</a> module needs a data type for what verbs are supposed
to mean: well, <span class="extract"><span class="extract-syntax">binary_predicate</span></span> is perfect for that.
</p>

<pre class="definitions code-font"><span class="definition-keyword">define</span> <span class="constant-syntax">VERB_MEANING_LINGUISTICS_TYPE</span><span class="plain-syntax"> </span><span class="reserved-syntax">struct</span><span class="plain-syntax"> </span><span class="reserved-syntax">binary_predicate</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">VERB_MEANING_REVERSAL_LINGUISTICS_CALLBACK</span><span class="plain-syntax"> </span><a href="3-bp.html#SP16" class="function-link"><span class="function-syntax">BinaryPredicates::get_reversal</span></a>
<span class="definition-keyword">define</span> <span class="constant-syntax">VERB_MEANING_EQUALITY</span><span class="plain-syntax"> </span><span class="identifier-syntax">R_equality</span>
<span class="definition-keyword">define</span> <span class="constant-syntax">VERB_MEANING_POSSESSION</span><span class="plain-syntax"> </span><span class="identifier-syntax">a_has_b_predicate</span>
</pre>
<p class="commentary firstcommentary"><a id="SP6" class="paragraph-anchor"></a><b>&#167;6. Combining the terms.</b>For handling the terms individually, see <a href="3-bptd.html" class="internal">Binary Predicate Term Details</a>.
</p>

<p class="commentary">Inform makes only very sparing use of the ability to define terms which have
no kind; this deactivates certain type-checks. It almost but not quite works to
use <span class="extract"><span class="extract-syntax">value</span></span> instead, and almost but not quite works to default null terms to
<span class="extract"><span class="extract-syntax">value</span></span> rather than to <span class="extract"><span class="extract-syntax">object</span></span>; the difficulty in that case comes with spatial
containment, i.e., "X is in Y". See the test cases <span class="extract"><span class="extract-syntax">MetaRelations</span></span>,
<span class="extract"><span class="extract-syntax">ContainmentScanning</span></span> and <span class="extract"><span class="extract-syntax">RelevantRelations</span></span> before fooling with any of this.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="function-syntax">BinaryPredicates::kind</span><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bp</span><span class="plain-syntax"> == </span><span class="identifier-syntax">R_equality</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::binary_con</span><span class="plain-syntax">(</span><span class="identifier-syntax">CON_relation</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bp</span><span class="plain-syntax"> == </span><span class="identifier-syntax">R_empty</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::binary_con</span><span class="plain-syntax">(</span><span class="identifier-syntax">CON_relation</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">, </span><span class="identifier-syntax">K_value</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K0</span><span class="plain-syntax"> = </span><a href="3-bp.html#SP7" class="function-link"><span class="function-syntax">BinaryPredicates::term_kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, </span><span class="constant-syntax">0</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="identifier-syntax">K1</span><span class="plain-syntax"> = </span><a href="3-bp.html#SP7" class="function-link"><span class="function-syntax">BinaryPredicates::term_kind</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, </span><span class="constant-syntax">1</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K0</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">K0</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K_object</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">K1</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">K1</span><span class="plain-syntax"> = </span><span class="identifier-syntax">K_object</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">Kinds::binary_con</span><span class="plain-syntax">(</span><span class="identifier-syntax">CON_relation</span><span class="plain-syntax">, </span><span class="identifier-syntax">K0</span><span class="plain-syntax">, </span><span class="identifier-syntax">K1</span><span class="plain-syntax">);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP7" class="paragraph-anchor"></a><b>&#167;7. </b>Details of the terms:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">kind</span><span class="plain-syntax"> *</span><span class="function-syntax">BinaryPredicates::term_kind</span><button class="popup" onclick="togglePopup('usagePopup1')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup1">Usage of <span class="code-font"><span class="function-syntax">BinaryPredicates::term_kind</span></span>:<br/><a href="3-bp.html#SP6">&#167;6</a><br/>Binary Predicate Families - <a href="3-bpf.html#SP6">&#167;6</a><br/>Type Check Propositions - <a href="4-tcp.html#SP7">&#167;7</a>, <a href="4-tcp.html#SP9_1">&#167;9.1</a><br/>Sentence Conversions - <a href="5-sc.html#SP2_5">&#167;2.5</a><br/>Simplifications - <a href="5-smp.html#SP2_1">&#167;2.1</a>, <a href="5-smp.html#SP8">&#167;8</a>, <a href="5-smp.html#SP15">&#167;15</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bp</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to find kind of null relation"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><a href="3-bptd.html#SP7" class="function-link"><span class="function-syntax">BPTerms::kind</span></a><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">term_details</span><span class="plain-syntax">[</span><span class="identifier-syntax">t</span><span class="plain-syntax">]));</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="function-syntax">BinaryPredicates::get_term_as_fn_of_other</span><button class="popup" onclick="togglePopup('usagePopup2')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup2">Usage of <span class="code-font"><span class="function-syntax">BinaryPredicates::get_term_as_fn_of_other</span></span>:<br/>Terms - <a href="4-trm.html#SP11">&#167;11</a><br/>Simplifications - <a href="5-smp.html#SP13">&#167;13</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">t</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bp</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to find function of null relation"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">term_details</span><span class="plain-syntax">[</span><span class="identifier-syntax">t</span><span class="plain-syntax">].</span><span class="element-syntax">function_of_other</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP8" class="paragraph-anchor"></a><b>&#167;8. </b>And as a convenience:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">BinaryPredicates::set_index_details</span><button class="popup" onclick="togglePopup('usagePopup3')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup3">Usage of <span class="code-font"><span class="function-syntax">BinaryPredicates::set_index_details</span></span>:<br/>The Equality Relation - <a href="3-ter.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">left</span><span class="plain-syntax">, </span><span class="reserved-syntax">char</span><span class="plain-syntax"> *</span><span class="identifier-syntax">right</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">left</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">term_details</span><span class="plain-syntax">[0].</span><span class="element-syntax">index_term_as</span><span class="plain-syntax"> = </span><span class="identifier-syntax">left</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">reversal</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">term_details</span><span class="plain-syntax">[1].</span><span class="element-syntax">index_term_as</span><span class="plain-syntax"> = </span><span class="identifier-syntax">left</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">right</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">term_details</span><span class="plain-syntax">[1].</span><span class="element-syntax">index_term_as</span><span class="plain-syntax"> = </span><span class="identifier-syntax">right</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">reversal</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">term_details</span><span class="plain-syntax">[0].</span><span class="element-syntax">index_term_as</span><span class="plain-syntax"> = </span><span class="identifier-syntax">right</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP9" class="paragraph-anchor"></a><b>&#167;9. Making the equality relation.</b>As we shall see below, BPs are almost always created in matched pairs. There
is just one exception: equality. This is a very polymorphic relation indeed,
and its terms have a null domain to impose no restrictions at all.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="function-syntax">BinaryPredicates::make_equality</span><button class="popup" onclick="togglePopup('usagePopup4')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup4">Usage of <span class="code-font"><span class="function-syntax">BinaryPredicates::make_equality</span></span>:<br/>The Equality Relation - <a href="3-ter.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">bp_family</span><span class="plain-syntax"> *</span><span class="identifier-syntax">family</span><span class="plain-syntax">, </span><span class="identifier-syntax">word_assemblage</span><span class="plain-syntax"> </span><span class="identifier-syntax">WA</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax"> = </span><a href="3-bp.html#SP11" class="function-link"><span class="function-syntax">BinaryPredicates::make_single</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">family</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><a href="3-bptd.html#SP2" class="function-link"><span class="function-syntax">BPTerms::new</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">), </span><a href="3-bptd.html#SP2" class="function-link"><span class="function-syntax">BPTerms::new</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">NULL</span><span class="plain-syntax">),</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">I</span><span class="string-syntax">"is"</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">WA</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">reversal</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bp</span><span class="plain-syntax">; </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">right_way_round</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">BINARY_PREDICATE_CREATED_CALCULUS_CALLBACK</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">BINARY_PREDICATE_CREATED_CALCULUS_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, </span><span class="identifier-syntax">WA</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bp</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP10" class="paragraph-anchor"></a><b>&#167;10. Making a pair of relations.</b>Every other BP belongs to a matched pair, in which each is the reversal of
the other. The one which is the wrong way round is never used in compilation,
because it will long before that have been reversed, so we only fill in
details of how to compile the BP for the one which is the right way round.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="function-syntax">BinaryPredicates::make_pair</span><button class="popup" onclick="togglePopup('usagePopup5')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup5">Usage of <span class="code-font"><span class="function-syntax">BinaryPredicates::make_pair</span></span>:<br/>The Equality Relation - <a href="3-ter.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">bp_family</span><span class="plain-syntax"> *</span><span class="identifier-syntax">family</span><span class="plain-syntax">,</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">bp_term_details</span><span class="plain-syntax"> </span><span class="identifier-syntax">left_term</span><span class="plain-syntax">, </span><span class="reserved-syntax">bp_term_details</span><span class="plain-syntax"> </span><span class="identifier-syntax">right_term</span><span class="plain-syntax">,</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">namer</span><span class="plain-syntax">,</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mtf</span><span class="plain-syntax">, </span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tf</span><span class="plain-syntax">, </span><span class="identifier-syntax">word_assemblage</span><span class="plain-syntax"> </span><span class="identifier-syntax">source_name</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, *</span><span class="identifier-syntax">bpr</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">n</span><span class="plain-syntax">)</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">TEMPORARY_TEXT</span><span class="plain-syntax">(</span><span class="identifier-syntax">nr</span><span class="plain-syntax">)</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Str::copy</span><span class="plain-syntax">(</span><span class="identifier-syntax">n</span><span class="plain-syntax">, </span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">n</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">n</span><span class="plain-syntax">, </span><span class="string-syntax">"nameless"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">Str::copy</span><span class="plain-syntax">(</span><span class="identifier-syntax">nr</span><span class="plain-syntax">, </span><span class="identifier-syntax">namer</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Str::len</span><span class="plain-syntax">(</span><span class="identifier-syntax">nr</span><span class="plain-syntax">) == </span><span class="constant-syntax">0</span><span class="plain-syntax">) </span><span class="identifier-syntax">WRITE_TO</span><span class="plain-syntax">(</span><span class="identifier-syntax">nr</span><span class="plain-syntax">, </span><span class="string-syntax">"%S-r"</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">  = </span><a href="3-bp.html#SP11" class="function-link"><span class="function-syntax">BinaryPredicates::make_single</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">family</span><span class="plain-syntax">, </span><span class="identifier-syntax">left_term</span><span class="plain-syntax">, </span><span class="identifier-syntax">right_term</span><span class="plain-syntax">, </span><span class="identifier-syntax">n</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">mtf</span><span class="plain-syntax">, </span><span class="identifier-syntax">tf</span><span class="plain-syntax">, </span><span class="identifier-syntax">source_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bpr</span><span class="plain-syntax"> = </span><a href="3-bp.html#SP11" class="function-link"><span class="function-syntax">BinaryPredicates::make_single</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">family</span><span class="plain-syntax">, </span><span class="identifier-syntax">right_term</span><span class="plain-syntax">, </span><span class="identifier-syntax">left_term</span><span class="plain-syntax">, </span><span class="identifier-syntax">nr</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">, </span><span class="identifier-syntax">WordAssemblages::lit_0</span><span class="plain-syntax">());</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">reversal</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bpr</span><span class="plain-syntax">; </span><span class="identifier-syntax">bpr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">reversal</span><span class="plain-syntax"> = </span><span class="identifier-syntax">bp</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">right_way_round</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">; </span><span class="identifier-syntax">bpr</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">right_way_round</span><span class="plain-syntax"> = </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">WordAssemblages::nonempty</span><span class="plain-syntax">(</span><span class="identifier-syntax">source_name</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">        #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">BINARY_PREDICATE_CREATED_CALCULUS_CALLBACK</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">BINARY_PREDICATE_CREATED_CALCULUS_CALLBACK</span><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, </span><span class="identifier-syntax">source_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    }</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bp</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP11" class="paragraph-anchor"></a><b>&#167;11. BP construction.</b>The following routine should only ever be called from the two above.
</p>

<p class="commentary">It looks a little asymmetric that the "make true function" schema <span class="extract"><span class="extract-syntax">mtf</span></span> is an
argument here, but the "make false function" isn't; that's just because
Inform finds this convenient. A "make false" can easily be added later.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="function-syntax">BinaryPredicates::make_single</span><button class="popup" onclick="togglePopup('usagePopup6')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup6">Usage of <span class="code-font"><span class="function-syntax">BinaryPredicates::make_single</span></span>:<br/><a href="3-bp.html#SP9">&#167;9</a>, <a href="3-bp.html#SP10">&#167;10</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">bp_family</span><span class="plain-syntax"> *</span><span class="identifier-syntax">family</span><span class="plain-syntax">,</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">bp_term_details</span><span class="plain-syntax"> </span><span class="identifier-syntax">left_term</span><span class="plain-syntax">, </span><span class="reserved-syntax">bp_term_details</span><span class="plain-syntax"> </span><span class="identifier-syntax">right_term</span><span class="plain-syntax">,</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="identifier-syntax">name</span><span class="plain-syntax">, </span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">mtf</span><span class="plain-syntax">, </span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">tf</span><span class="plain-syntax">, </span><span class="identifier-syntax">word_assemblage</span><span class="plain-syntax"> </span><span class="identifier-syntax">rn</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax"> = </span><span class="identifier-syntax">CREATE</span><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">relation_family</span><span class="plain-syntax"> = </span><span class="identifier-syntax">family</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">relation_name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">rn</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">bp_created_at</span><span class="plain-syntax"> = </span><span class="identifier-syntax">current_sentence</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">debugging_log_name</span><span class="plain-syntax"> = </span><span class="identifier-syntax">Str::duplicate</span><span class="plain-syntax">(</span><span class="identifier-syntax">name</span><span class="plain-syntax">);</span>

<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">term_details</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">left_term</span><span class="plain-syntax">; </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">term_details</span><span class="plain-syntax">[1] = </span><span class="identifier-syntax">right_term</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="comment-syntax"> the </span><span class="extract"><span class="extract-syntax">reversal</span></span><span class="comment-syntax"> and the </span><span class="extract"><span class="extract-syntax">right_way_round</span></span><span class="comment-syntax"> field must be set by the caller</span>

<span class="plain-syntax">    </span><span class="comment-syntax"> for use in code compilation</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">task_functions</span><span class="plain-syntax">[0] = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">; </span><span class="comment-syntax"> not used: there's no task 0</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">task_functions</span><span class="plain-syntax">[</span><span class="constant-syntax">TEST_ATOM_TASK</span><span class="plain-syntax">] = </span><span class="identifier-syntax">tf</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">task_functions</span><span class="plain-syntax">[</span><span class="constant-syntax">NOW_ATOM_TRUE_TASK</span><span class="plain-syntax">] = </span><span class="identifier-syntax">mtf</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">task_functions</span><span class="plain-syntax">[</span><span class="constant-syntax">NOW_ATOM_FALSE_TASK</span><span class="plain-syntax">] = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_parent_optimisation_proviso</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_parent_optimisation_ranger</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    </span><span class="comment-syntax"> for use by the A-parser</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">knowledge_about_bp</span><span class="plain-syntax"> = </span><span class="identifier-syntax">RelationSubjects::new</span><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifndef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">knowledge_about_bp</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>

<span class="plain-syntax">    </span><span class="comment-syntax"> details for particular kinds of relation</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">family_specific</span><span class="plain-syntax"> = </span><span class="identifier-syntax">NULL_GENERAL_POINTER</span><span class="plain-syntax">;</span>

<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">compilation_data</span><span class="plain-syntax"> = </span><span class="identifier-syntax">RTRelations::new_compilation_data</span><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>

<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bp</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP12" class="paragraph-anchor"></a><b>&#167;12. BP and term logging.</b></p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">BinaryPredicates::log_term_details</span><span class="plain-syntax">(</span><span class="reserved-syntax">bp_term_details</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bptd</span><span class="plain-syntax">, </span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  function(%d): $i\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">bptd</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">function_of_other</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::nonempty</span><span class="plain-syntax">(</span><span class="identifier-syntax">bptd</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">called_name</span><span class="plain-syntax">)) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  term %d is '%W'\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">bptd</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">called_name</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bptd</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">implies_infs</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">wording</span><span class="plain-syntax"> </span><span class="identifier-syntax">W</span><span class="plain-syntax"> = </span><span class="identifier-syntax">TERM_DOMAIN_WORDING_FUNCTION</span><span class="plain-syntax">(</span><span class="identifier-syntax">bptd</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">implies_infs</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">Wordings::nonempty</span><span class="plain-syntax">(</span><span class="identifier-syntax">W</span><span class="plain-syntax">)) </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  term %d has domain %W\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">i</span><span class="plain-syntax">, </span><span class="identifier-syntax">W</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    }</span>
<span class="plain-syntax">}</span>

<span class="reserved-syntax">void</span><span class="plain-syntax"> </span><span class="function-syntax">BinaryPredicates::log</span><button class="popup" onclick="togglePopup('usagePopup7')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup7">Usage of <span class="code-font"><span class="function-syntax">BinaryPredicates::log</span></span>:<br/>Calculus Module - <a href="1-cm.html#SP3">&#167;3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bp</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) { </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"&lt;null-BP&gt;\n"</span><span class="plain-syntax">); </span><span class="reserved-syntax">return</span><span class="plain-syntax">; }</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifdef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"BP%d &lt;%S&gt; - %s way round - %s\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">debugging_log_name</span><span class="plain-syntax">, </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">right_way_round</span><span class="plain-syntax">?</span><span class="string-syntax">"right"</span><span class="plain-syntax">:</span><span class="string-syntax">"wrong"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">ExplicitRelations::form_to_text</span><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">));</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">ifndef</span><span class="plain-syntax"> </span><span class="identifier-syntax">CORE_MODULE</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"BP%d &lt;%S&gt; - %s way round\n"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">        </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="identifier-syntax">allocation_id</span><span class="plain-syntax">, </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">debugging_log_name</span><span class="plain-syntax">, </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">right_way_round</span><span class="plain-syntax">?</span><span class="string-syntax">"right"</span><span class="plain-syntax">:</span><span class="string-syntax">"wrong"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    #</span><span class="identifier-syntax">endif</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">for</span><span class="plain-syntax"> (</span><span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="identifier-syntax">i</span><span class="plain-syntax">=0; </span><span class="identifier-syntax">i</span><span class="plain-syntax">&lt;2; </span><span class="identifier-syntax">i</span><span class="plain-syntax">++) </span><a href="3-bp.html#SP12" class="function-link"><span class="function-syntax">BinaryPredicates::log_term_details</span></a><span class="plain-syntax">(&amp;</span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">term_details</span><span class="plain-syntax">[</span><span class="identifier-syntax">i</span><span class="plain-syntax">], </span><span class="identifier-syntax">i</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  test: $i\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">task_functions</span><span class="plain-syntax">[</span><span class="constant-syntax">TEST_ATOM_TASK</span><span class="plain-syntax">]);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  make true: $i\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">task_functions</span><span class="plain-syntax">[</span><span class="constant-syntax">NOW_ATOM_TRUE_TASK</span><span class="plain-syntax">]);</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOG</span><span class="plain-syntax">(</span><span class="string-syntax">"  make false: $i\n"</span><span class="plain-syntax">, </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">task_functions</span><span class="plain-syntax">[</span><span class="constant-syntax">NOW_ATOM_FALSE_TASK</span><span class="plain-syntax">]);</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP13" class="paragraph-anchor"></a><b>&#167;13. Relation names.</b>This is a useful little nonterminal to spot the names of relation, such as
"adjacency". (Note: not "adjacency relation".) This should only be used when
there is good reason to suspect that the word in question is the name of a
relation, so the fact that it runs relatively slowly does not matter.
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="function-syntax">&lt;relation-name&gt;</span><span class="plain-syntax"> </span><span class="identifier-syntax">internal</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="identifier-syntax">LOOP_OVER</span><span class="plain-syntax">(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">, </span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax">)</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">WordAssemblages::compare_with_wording</span><span class="plain-syntax">(&amp;(</span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">relation_name</span><span class="plain-syntax">), </span><span class="identifier-syntax">W</span><span class="plain-syntax">)) {</span>
<span class="plain-syntax">            ==&gt; { -, </span><span class="identifier-syntax">bp</span><span class="plain-syntax"> }; </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">        }</span>
<span class="plain-syntax">    ==&gt; { </span><span class="identifier-syntax">fail</span><span class="plain-syntax"> </span><span class="identifier-syntax">nonterminal</span><span class="plain-syntax"> };</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP14" class="paragraph-anchor"></a><b>&#167;14. </b></p>

<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">text_stream</span><span class="plain-syntax"> *</span><span class="function-syntax">BinaryPredicates::get_log_name</span><button class="popup" onclick="togglePopup('usagePopup8')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup8">Usage of <span class="code-font"><span class="function-syntax">BinaryPredicates::get_log_name</span></span>:<br/>Atomic Propositions - <a href="4-ap.html#SP14_3">&#167;14.3</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">debugging_log_name</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP15" class="paragraph-anchor"></a><b>&#167;15. Miscellaneous access routines.</b></p>

<pre class="displayed-code all-displayed-code code-font">
<span class="identifier-syntax">parse_node</span><span class="plain-syntax"> *</span><span class="function-syntax">BinaryPredicates::get_bp_created_at</span><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">bp_created_at</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP16" class="paragraph-anchor"></a><b>&#167;16. </b>Reversing:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="function-syntax">BinaryPredicates::get_reversal</span><button class="popup" onclick="togglePopup('usagePopup9')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup9">Usage of <span class="code-font"><span class="function-syntax">BinaryPredicates::get_reversal</span></span>:<br/><a href="3-bp.html#SP5">&#167;5</a><br/>Sentence Conversions - <a href="5-sc.html#SP2_7_1">&#167;2.7.1</a><br/>Simplifications - <a href="5-smp.html#SP11">&#167;11</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bp</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="identifier-syntax">internal_error</span><span class="plain-syntax">(</span><span class="string-syntax">"tried to find reversal of null relation"</span><span class="plain-syntax">);</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">reversal</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">BinaryPredicates::is_the_wrong_way_round</span><button class="popup" onclick="togglePopup('usagePopup10')"><span class="comment-syntax">?</span><span class="popuptext" id="usagePopup10">Usage of <span class="code-font"><span class="function-syntax">BinaryPredicates::is_the_wrong_way_round</span></span>:<br/>Type Check Propositions - <a href="4-tcp.html#SP4_6">&#167;4.6</a><br/>Simplifications - <a href="5-smp.html#SP11">&#167;11</a></span></button><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) &amp;&amp; (</span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">right_way_round</span><span class="plain-syntax"> == </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">)) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP17" class="paragraph-anchor"></a><b>&#167;17. </b>For compiling code from conditions:
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="function-syntax">BinaryPredicates::get_test_function</span><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">task_functions</span><span class="plain-syntax">[</span><span class="constant-syntax">TEST_ATOM_TASK</span><span class="plain-syntax">];</span>
<span class="plain-syntax">}</span>
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">BinaryPredicates::can_be_made_true_at_runtime</span><span class="plain-syntax">(</span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> ((</span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">task_functions</span><span class="plain-syntax">[</span><span class="constant-syntax">NOW_ATOM_TRUE_TASK</span><span class="plain-syntax">]) ||</span>
<span class="plain-syntax">        (</span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">reversal</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">task_functions</span><span class="plain-syntax">[</span><span class="constant-syntax">NOW_ATOM_TRUE_TASK</span><span class="plain-syntax">])) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP18" class="paragraph-anchor"></a><b>&#167;18. Loop schema.</b>The predicate-calculus engine compiles much better loops if we can help it by
providing an I6 schema of a loop header solving the following problem:
</p>

<p class="commentary">Loop a variable \(v\) (in the schema, <span class="extract"><span class="extract-syntax">*1</span></span>) over all possible \(x\) such that
\(R(x, t)\), for some fixed \(t\) (in the schema, <span class="extract"><span class="extract-syntax">*2</span></span>).
</p>

<p class="commentary">If we can't do this, it will have to fall back on the brute force method of
looping over all \(x\) in the left domain of \(R\) and testing every possible \(R(x, t)\).
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="reserved-syntax">int</span><span class="plain-syntax"> </span><span class="function-syntax">BinaryPredicates::write_optimised_loop_schema</span><span class="plain-syntax">(</span><span class="reserved-syntax">i6_schema</span><span class="plain-syntax"> *</span><span class="identifier-syntax">sch</span><span class="plain-syntax">, </span><span class="reserved-syntax">binary_predicate</span><span class="plain-syntax"> *</span><span class="identifier-syntax">bp</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bp</span><span class="plain-syntax"> == </span><span class="identifier-syntax">NULL</span><span class="plain-syntax">) </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="3-bp.html#SP18_1" class="named-paragraph-link"><span class="named-paragraph">Try loop ranger optimisation</span><span class="named-paragraph-number">18.1</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="named-paragraph-container code-font"><a href="3-bp.html#SP18_2" class="named-paragraph-link"><span class="named-paragraph">Try loop parent optimisation subject to a proviso</span><span class="named-paragraph-number">18.2</span></a></span><span class="plain-syntax">;</span>
<span class="plain-syntax">    </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">FALSE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">}</span>
</pre>
<p class="commentary firstcommentary"><a id="SP18_1" class="paragraph-anchor"></a><b>&#167;18.1. </b>Some relations \(R\) provide a "ranger" routine, <span class="extract"><span class="extract-syntax">R</span></span>, which is such that
<span class="extract"><span class="extract-syntax">R(t)</span></span> supplies the first "child" of \(t\) and <span class="extract"><span class="extract-syntax">R(t, n)</span></span> supplies the next
"child" after \(n\). Thus <span class="extract"><span class="extract-syntax">R</span></span> iterates through some linked list of all the
objects \(x\) such that \(R(x, t)\).
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Try loop ranger optimisation</span><span class="named-paragraph-number">18.1</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_parent_optimisation_ranger</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><a href="3-cs.html#SP6" class="function-link"><span class="function-syntax">Calculus::Schemas::modify</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="string-syntax">"for (*1=%s(*2): *1: *1=%s(*2,*1))"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_parent_optimisation_ranger</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_parent_optimisation_ranger</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-bp.html#SP18">&#167;18</a>.</li></ul>
<p class="commentary firstcommentary"><a id="SP18_2" class="paragraph-anchor"></a><b>&#167;18.2. </b>Other relations make use of the I6 object tree, in cases where \(R(x, t)\)
is true if and only if \(t\) is an object which is the parent of \(x\) in the
I6 object tree and some routine associated with \(R\), called its
proviso <span class="extract"><span class="extract-syntax">P</span></span>, is such that <span class="extract"><span class="extract-syntax">P(x) == t</span></span>. For example, worn-by(\(x\), \(t\))
is true iff \(t\) is the parent of \(x\) and <span class="extract"><span class="extract-syntax">WearerOf(x) == t</span></span>. The proviso
ensures that we don't falsely pick up, say, items carried by \(t\) which
aren't being worn, or aren't even clothing.
</p>

<p class="commentary"><span class="named-paragraph-container code-font"><span class="named-paragraph-defn">Try loop parent optimisation subject to a proviso</span><span class="named-paragraph-number">18.2</span></span><span class="comment-syntax"> =</span>
</p>

<pre class="displayed-code all-displayed-code code-font">
<span class="plain-syntax">    </span><span class="reserved-syntax">if</span><span class="plain-syntax"> (</span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_parent_optimisation_proviso</span><span class="plain-syntax">) {</span>
<span class="plain-syntax">        </span><a href="3-cs.html#SP6" class="function-link"><span class="function-syntax">Calculus::Schemas::modify</span></a><span class="plain-syntax">(</span><span class="identifier-syntax">sch</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="string-syntax">"objectloop (*1 in *2) if (%s(*1)==parent(*1))"</span><span class="plain-syntax">,</span>
<span class="plain-syntax">            </span><span class="identifier-syntax">bp</span><span class="plain-syntax">-&gt;</span><span class="element-syntax">loop_parent_optimisation_proviso</span><span class="plain-syntax">);</span>
<span class="plain-syntax">        </span><span class="reserved-syntax">return</span><span class="plain-syntax"> </span><span class="identifier-syntax">TRUE</span><span class="plain-syntax">;</span>
<span class="plain-syntax">    }</span>
</pre>
<ul class="endnotetexts"><li>This code is used in <a href="3-bp.html#SP18">&#167;18</a>.</li></ul>
<nav role="progress"><div class="progresscontainer">
    <ul class="progressbar"><li class="progressprev"><a href="3-bptd.html">&#10094;</a></li><li class="progresschapter"><a href="P-wtmd.html">P</a></li><li class="progresschapter"><a href="1-cm.html">1</a></li><li class="progresschapter"><a href="2-up.html">2</a></li><li class="progresscurrentchapter">3</li><li class="progresssection"><a href="3-bpf.html">bpf</a></li><li class="progresssection"><a href="3-bptd.html">bptd</a></li><li class="progresscurrent">bp</li><li class="progresssection"><a href="3-ter.html">ter</a></li><li class="progresssection"><a href="3-cs.html">cs</a></li><li class="progresschapter"><a href="4-trm.html">4</a></li><li class="progresschapter"><a href="5-sc.html">5</a></li><li class="progressnext"><a href="3-ter.html">&#10095;</a></li></ul></div>
</nav><!-- End of weave -->

		</main>
	</body>
</html>

